import os

from numpy import size
print('public1')
import logging
from PyQt5.QtCore import  pyqtSignal, QObject
import re
import requests
print('public2')
from MySQLHelper_xue import MySQLHelper_xue
import winreg
import datetime, time
import random
import pymysql
print('public3')
from random import randint,choice,uniform
from datetime import datetime
from sqlalchemy import create_engine, false, table
from sqlalchemy.orm import sessionmaker
import logging
print('public1')

from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from mysql.connector import pooling
from random import randint  # 添加这行，或者使用 random.randint
print('public1')
import random
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '.'))
import re
print('public321')
from typing import Optional, List, Dict, Any, Union
import mysql.connector
from mysql.connector import Error
print('publica31')
from typing import Optional, List, Dict, Any, Union
import mysql.connector
from mysql.connector import Error
import logging
print('public31')

from datetime import datetime
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from PyQt5.QtCore import QAbstractTableModel, Qt
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import winreg
print('public1')

from pypinyin import pinyin, lazy_pinyin, Style
import time, base64, requests
# 将中文转换为拼音列表，包含声调
import time, base64, json, requests
from pypinyin import pinyin, Style
# 将中文转换为首字母大写的拼音字符串
import uuid
import random
import string
import json
print('publiddc1')

# 将JSON字符串解析为Python字典
def getphonevalidcode(api_url):
# 将JSON字符串解析为Python字典
    try:
        response = requests.get(api_url)
        json_data = response.text
        match = re.search(r'\b\d{4}\b', json_data)
        if match:
            print(match.group(0))
            return match.group(0)
        return None
         
    except Exception as e:
        print(f"获取验证码失败: {str(e)}")
        logging.error(f"获取验证码失败: {str(e)}")
        return None

def generate_custom_uuid(min_length=6, max_length=8):
    # 生成一个标准的 UUID 并转换为字母和数字的字符串
    unique_id = uuid.uuid4().hex

    # 确保以字母开头
    if unique_id[0].isdigit():
        unique_id = random.choice(string.ascii_letters) + unique_id[1:]

    # 随机选择长度在 6 到 8 之间
    length = random.randint(min_length, max_length)
    return unique_id[:length]
def chinese_to_pinyin_capitalized(chinese):
    pinyin_list = lazy_pinyin(chinese)
    return ' '.join([pinyin.capitalize() for pinyin in pinyin_list])

 
def convert_to_pinyin(chinese_text):
    # 使用 pypinyin 将中文转换为拼音
    pinyin_list = pinyin(chinese_text, style=Style.NORMAL)
    # 将拼音列表转换为字符串
    pinyin_str = ''.join([item[0] for item in pinyin_list])
    return pinyin_str

proxycertstr='customer-bd0a10fb-country-US-session-853a16d1bd954c2-time-1440:3c0d7415@proxy.ipipgo.com:31212'
valid_username='zhangsir8888'
valid_password='Zb_200407'
heartsleep=0.8

def is_floatstr(string):
    pattern = re.compile(r'^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0 - 9]+)?$')
    return pattern.fullmatch(string) is not None


user_agents = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
]
def move_mouse_to_position(driver, position):
    try:
        # Get the total height of the page
        total_height = driver.execute_script("return document.body.scrollHeight")
        actions = ActionChains(driver)
    # Calculate the target y-coordinate
        target_y = total_height * position

        # Get the current y-coordinate of the mouse
        current_y = 0  # Assuming the mouse starts at the top of the page


        # Move the mouse in small steps
        step_size = 10  # Adjust the step size as needed
        while current_y < target_y:
            driver.execute_script("window.scrollBy(0, arguments[0]);", step_size)
            current_y += step_size
            time.sleep(0.03)  # Add a small delay between steps

        # Ensure the final position is reached
        actions.move_by_offset(0, target_y - current_y).perform()   
    except Exception as e:
        print(f"移动鼠标失败: {str(e)}")
def getexcept   (emsg):
        spec = [
            "'"
            '<', '>', '$', '*', '&', '%', '.', '"', '+', '-', '@', '"', '\\','\n','\r','\t'
            '(', ')', ' ', '#', '.', '//', '#'
        ]
        for sp in spec:
            if sp in emsg:
                emsg = emsg.replace(sp, ' ')
        emsg = emsg.replace('"', '').replace("'", "")
        return emsg.strip()
def except_to_db_rpa(self,dbhelper,error_details):
        logmessage=f'-->rpa->{error_details}  {datetime.now()}'
        logmessage=getexcept(logmessage)
        logging.error("An error occurred->" + logmessage, exc_info=True)   
        self.sender.textUpdateSignal.emit(logmessage)
        sql = f" insert into crawlexcept(opdate,exceptcon)  values(now(),%s)"
        try:
            dbhelper.execute(sql,(logmessage,))
        except Exception as e:
            print('连接数据库出错',e)
def except_to_db(self,dbhelper,error_details):
    try:
        logmessage=f'{error_details}  {datetime.now()}'
        logmessage=getexcept(logmessage)
        # logging.error("An error occurred->" + logmessage, exc_info=True)   
        self.sender.textUpdateSignal.emit(logmessage)
        sql = f" insert into crawlexcept(opdate,exceptcon)  values(now(),%s)"
        dbhelper.execute(sql,(logmessage,)) 
    except Exception as e:
        print(f"处理异常出错: {str(e)}")
            
       
            
def process_captcha_image_text(driver,xpath_image):
    # 验证码抠图

    try:
        img = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH,xpath_image))
        )           
        actions = ActionChains(driver)
        img_path='./验证码.png'
        img.screenshot(img_path)
        time.sleep(0.5)
        with open(img_path, 'rb') as f:
            img_data = base64.b64encode(f.read()).decode()
        api_post_url = "http://www.bingtop.com/ocr/upload/"
        with open(img_path,'rb') as pic_file:
            img64=base64.b64encode(pic_file.read())
        params = {
            "username": valid_username,
            "password": valid_password,
            "captchaData": img_data,
            "captchaType": 1001
        }
        # os.remove(img_path)
        # # 删除文件
        # os.remove(screenshot_path)
        response = requests.post(api_post_url, data=params)
        dictdata=json.loads(response.text)
        # 发送请求，获取第三方识别结果
        
        return dictdata       
    except Exception as e:
        print(f"获取验证码图片失败: {str(e)}")
        return None

    # Move the mouse to the target position
def process_captcha_image(driver):
    # 验证码抠图

    try:
        # 等待iframe加载
        wait=WebDriverWait(driver, 10)
        element=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[src*='seller-us.tiktok.com/preload']"))
        )
        
        # 切换到iframe
        # iframe = driver.find_element(By.CSS_SELECTOR, "iframe[src*='seller-us.tiktok.com/preload']")
        # driver.switch_to.frame(iframe)
        
        # 等待并获取验证码图片
        img = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH,'//*[@id=":r2:"]/div/div[2]/div/img'))
        )           
        actions = ActionChains(driver)

        # actions.move_to_element_with_offset(img, 100, 100).click().perform()
                                        
        
        img_path='./验证码.png'

    # 打开截图并截取验证码部分
       
        img.screenshot(img_path)
            # 点击登录
        time.sleep(0.5)
        # # 定位验证码
        with open(img_path, 'rb') as f:
            img_data = base64.b64encode(f.read()).decode()
        # 构建请求数据
        
        api_post_url = "http://www.bingtop.com/ocr/upload/"
        with open(img_path,'rb') as pic_file:
            img64=base64.b64encode(pic_file.read())
        params = {
            "username": valid_username,
            "password": valid_password,
            "captchaData": img_data,
            "captchaType": 2301
        }
        # os.remove(img_path)
        # # 删除文件
        # os.remove(screenshot_path)
        response = requests.post(api_post_url, data=params)
        dictdata=json.loads(response.text)
        # 发送请求，获取第三方识别结果
        poss=dictdata['data']['recognition'].split('|')
        # human_move_and_move(driver,img)
        (x1,y1)=poss[0].split(',')
        (x2,y2)=poss[1].split(',')
        one_offset = randint(-1, 1)
        one_offset=0
        a1=int(x1)-size['width']/2
        b1=int(y1)-size['height']/2
        a2=int(x2)-size['width']/2
        b2=int(y2)-size['height']/2
        # precise_click_with_pause(driver,img,a1-one_offset,b1-one_offset)
        # precise_click_with_pause(driver,img,a2+one_offset,b2-one_offset)    
        actions.move_to_element_with_offset(img, a1+one_offset, b1+one_offset).click().perform()
        time.sleep(2*heartsleep*random.random())
        actions.move_to_element_with_offset(img, a2+one_offset, b2+one_offset).click().perform()
        return img       
    except Exception as e:
        print(f"获取验证码图片失败: {str(e)}")
        return None
def has_ip_address(text):
    ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
    return bool(re.search(ip_pattern, text))

def getverycode(mobileurl):
    varcode=None
    return varcode
def extract_float(s):
    match = re.search(r'\d+\.\d+', s)
    if match:
        return match.group(1)
    else:
        return "未找到匹配的内容"


def generate_random_ua():
    return random.choice(user_agents)


def get_chrome_path_windows():
    try:
        key = winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe")
        value, _ = winreg.QueryValueEx(key, None)
        return value
    except FileNotFoundError:
        return None

config = {
            "user": "root",
            "password":"Zb_200407",
            "host": "gz-cdb-d4j7h16x.sql.tencentcdb.com",
            "database": "eas",
            'port':22333,
            'connect_timeout': 10,
            'charset': 'utf8mb4',
            'pool_reset_session': True,
            'use_pure': True
        }

 


def write_log(con, data, text):
    # 用文本框记录日志信息
    # 数据库也写信息
    logging.info(f'{data}\n')
    sql = f"insert into us_logg(disknumber,username,ip,opdate,gateway,memo,action) values('{data['disknumber']}','{data['username']}','{data['ip']}',{data['datefunction']},'{data['gateway']}','{data['memo']}','{data['action']}')"
    con.dbexecute(sql)
    if not text is None:
        text.append(data)


def getaccountinfo():
    current_path = os.getcwd()
    fileaccounmt = os.path.join(current_path + "\\account.txt")
    logging.info(f'读取访问配置文件，配置文件存放于{fileaccounmt}\n')
    account_info = {}
    try:
        with open(fileaccounmt, 'r') as file:
            lines = file.readlines()
            for line in lines:
                line = line.strip()
                if line and '=' in line:
                    key, value = line.split('=')
                    account_info[key.strip()] = value.strip()
                    value = value.strip()
                    if ' ' in value:
                        account_info[key.strip()] = value.split(' ')[0].strip()

    except FileNotFoundError:
        logging.info(f'读取访问配置文件失败！，配置文件存放于{fileaccounmt}\n')

    finally:
        return account_info




def get_chrome_version():
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r"Software\Google\Chrome\BLBeacon")
        version, _ = winreg.QueryValueEx(key, "version")
        winreg.CloseKey(key)
        return version
    except WindowsError:
        return None


def get_chrome_path():
    try:
        key = winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe")
        value, _ = winreg.QueryValueEx(key, None)
        return value
    except FileNotFoundError:
        return None
def human_clear( element):  # 修改方法定义，添加 self 参数
        """模拟人工输入"""
        try:
            time.sleep(heartsleep *random.random())
            count=len(element.text  )
            if count<50:
                count=50
            # 逐字输入
            for ix  in range(count):
                element.send_keys(Keys.BACKSPACE)
                # 每个字符之间的延迟在 0.1-0.3 秒之间
                time.sleep(heartsleep * 0.2 *random.random())
            
            # 输入完成后的随机等待
            time.sleep(heartsleep  *random.random())
            
        except Exception as e:
            print(f"输入文字失败: {str(e)}")
def human_type( element, text):  # 修改方法定义，添加 self 参数
        """模拟人工输入"""
        try:
            # 先清空输入框
            element.clear()
            time.sleep(heartsleep *random.random())
            
            # 逐字输入
            for char in text:
                time.sleep(heartsleep * 0.1 *random.random())
                element.send_keys(char)
                # 每个字符之间的延迟在 0.1-0.3 秒之间
            
            # 输入完成后的随机等待
            time.sleep(heartsleep  *random.random())
            
        except Exception as e:
            print(f"输入文字失败: {str(e)}")
    
def random_sleep( min_seconds=0, max_seconds=1):
        """
        随机等待一段时间
        
        Args:
            min_seconds (float): 最小等待时间（秒）
            max_seconds (float): 最大等待时间（秒）
        
        Returns:
            float: 实际等待的时间
        """
        try:
            # 生成随机等待时间
            sleep_time = uniform(min_seconds, max_seconds)
            
            # 实际等待
            time.sleep(sleep_time)
            
            # 可选：记录等待信息
            print(f"等待 {sleep_time:.2f} 秒...")
            
            return sleep_time
            
        except Exception as e:
            print(f"随机等待出错: {str(e)}")
            # 如果出错，使用最小等待时间
            time.sleep(min_seconds)
            return min_seconds
def human_move_and_click(driver, element):
        """模拟人工移动鼠标并点击"""
        try:
            actions = ActionChains(driver)
            
            # 随机选择一个偏移量
            offset_x = randint(-5, 5)
            offset_y = randint(-5, 5)
            
            # 移动到元素附近
            actions.move_to_element_with_offset(element, offset_x, offset_y)
            actions.move_to_element(element)
            time.sleep(heartsleep *random.random())
            
            # 点击
            actions.click()
            actions.perform()
            time.sleep(heartsleep* 2 *random.random())
            # 点击后的随机等待
            
        except Exception as e:
            print(f"点击操作失败: {str(e)}")   

        
    
def human_move_and_move(driver, element):
        """模拟人工移动鼠标并点击"""
        try:
            actions = ActionChains(driver)
            
            # 随机选择一个偏移量
            offset_x = randint(-5, 5)
            offset_y = randint(-5, 5)
            
            # 移动到元素附近
            actions.move_to_element_with_offset(element, offset_x, offset_y)
            actions.move_to_element(element)
            time.sleep(heartsleep *random.random())
            
            # 点击
            # actions.click()
            actions.perform()
            time.sleep(heartsleep* 2 *random.random())
            # 点击后的随机等待
            
        except Exception as e:
            print(f"点击操作失败: {str(e)}")  
def precise_click_with_pause(driver, element, x_offset, y_offset, pause_time=0.5):
    try:
         
        time.sleep(0.3)  # 等待滚动完成
        
        # 创建 ActionChains
        actions = ActionChains(driver)
        
        # 添加1像素以内的随机误差
        random_x = x_offset #+ random.uniform(-1, 1)
        random_y = y_offset #+ random.uniform(-1, 1)
        
        # 移动到元素
        # actions.move_to_element(element)
        actions.move_to_element_with_offset(element, x_offset+1, y_offset+1)

        # # 添加偏移量
        # actions.move_by_offset(random_x+1, random_y+1)
        # actions.perform()
        
        # 停留指定时间
        time.sleep(pause_time)
        
        # 执行点击
        actions.click()
        actions.perform()
        
         
    except Exception as e:
        print(f"验证码点击操作失败: {str(e)}")
def human_move_and_offsetclick           (driver, element, offsetx,offsety):
        """模拟人工移动鼠标移动到指定坐标(offsetx,offsety)并点击"""
        try:
            actions = ActionChains(driver)
            
            # 移动到元素附近
            actions.move_to_element_with_offset(element, offsetx, offsety)
            actions.move_to_element(element)
            time.sleep(heartsleep *random.random())
            
            # 点击
            actions.click()
            actions.perform()
            time.sleep(heartsleep* 2 *random.random())
            # 点击后的随机等待
            
        except Exception as e:
            print(f"点击操作失败: {str(e)}")  
def testproxy( ):
        proxies = getproxyip(proxycertstr)
        start = int(round(time.time() * 1000))
        resp = None
        costTime = 0.0
        try:
            targetUrl = "http://myip.ipip.net"

            resp = requests.get(targetUrl, proxies=proxies, timeout=20)
            costTime = int(round(time.time() * 1000)) - start
            print(resp.text)
        except Exception as e:
            print(e)
            return 9999
        print("耗时：" + str(costTime) + "ms")

        return int(costTime / 1000)
def reset_proxy( driver):
        proxy = getproxyip(proxycertstr)
        if proxy != '' and has_ip_address(proxycertstr):
            # proxy_1 = proxy.split(':')
            driver.proxy = proxy

def getproxyip( proxystr):
        # original_str = "208.70.10.96:5868:zftfnuiq:boknwrr5myt0"
        # parts = proxystr.split(":")
        # new_str = f"{parts[2]}:{parts[3]}@{parts[0]}:{parts[1]}"
        proxies2 = {
            "http": f"http://{proxystr}",
            "https": f"https://{proxystr}"
        }
        print(proxies2)
        return proxies2
def getzlyproxyip( param=1):
        #param=0，国内代理，否则为国际代理
        proxyip = 'no proxy'
        try:
            apiUrl =proxycertstr #'http://api.ipipgo.com/ip?cty=US&c=1&pt=1&ft=txt&pat=\n&rep=1&key=0c4201f3&ts=240'
            if param == 0:
                apiUrl = 'http://api.ip.data5u.com/dynamic/get.html?order=a0aab4a6ac5b39318e5317e8800a119d&random=2&sep=3'
            res = requests.get(apiUrl).content.decode()
            # 按照\n分割获取到的IP
            ips = res.split('\n')
            # 利用每一个IP
            for proxyip2 in ips:

                if proxyip2.strip() == '':
                    continue
                else:
                    proxyip = proxyip2
                print(proxyip2)

        except Exception as e:
            print(f'getproxyip{e}')

        return proxyip
def getdrvier() :
            driver=None
            ua =user_agents[random.randint(0, len(user_agents) - 1)]
            chrome_options = webdriver.ChromeOptions()
            user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            chrome_options.add_argument(f'--user-agent={ua}')
            chrome_options.add_argument('--ignore-certificate-errors')
            chrome_options.add_argument('--ignore-ssl-errors')
            chrome_options.add_argument('--disable-extensions')  # 禁用扩展
            chrome_options.add_argument('--disable-software-rasterizer')  # 禁用软件光栅化
    # 添加常规选项
            chrome_options.add_argument('--disable-logging')  # 禁用日志
            chrome_options.add_argument('--log-level=3')  # 仅显示严重错误
            chrome_options.add_argument('--silent')  # 静默模式
            
            # 禁用开发者工具相关的警告
            chrome_options.add_experimental_option('excludeSwitches', [
                'enable-logging',
                'enable-automation'
            ])
            
            # 设置首选项
            prefs = {
                'devtools.preferences.currentDockState': '"undocked"',  # 开发者工具设置
                'devtools.timeline.hidden-categories': '["*"]',  # 隐藏所有类别
                'profile.default_content_setting_values.notifications': 2,  # 禁用通知
                'profile.default_content_settings.popups': 0  # 禁用弹窗
            }
            chrome_options.add_experimental_option('prefs', prefs)
            chrome_options.add_argument('--window-size=1920,1080')
            chrome_options.add_argument('--start-maximized')  # 最大化窗口
            chrome_options.add_argument('--force-device-scale-factor=1')  # 设置缩放比例为1
            chrome_options.add_argument('--high-dpi-support=1')  # 支持高DPI
            
            # 禁用缩放
            chrome_options.add_argument('--disable-gpu')
            chrome_options.add_argument('--disable-software-rasterizer')
            current_path=os.getcwd()
            chromedriver_path = os.path.join(current_path, "chromedriver.exe")
        # 创建 Service 对象并传入路径
            
            service = Service(executable_path=chromedriver_path)
            # 创建 WebDriver 实例时传入 Service 对象和 ChromeOptions
            driver = webdriver.Chrome(service=service, options=chrome_options)
            return driver   # driver.maximize_window()

            # 打开BOSS直聘
print('publiddtestc1')

if __name__ == '__main__':
   print(1)
   print('public main')
#    testproxy()
# #    reset_proxy(getdrvier())